    //Random Game Engine
    //Copyright (C) 2012  Nikolay Dionisov

    //This program is free software: you can redistribute it and/or modify
    //it under the terms of the GNU General Public License as published by
    //the Free Software Foundation, either version 3 of the License, or
    //(at your option) any later version.

    //This program is distributed in the hope that it will be useful,
    //but WITHOUT ANY WARRANTY; without even the implied warranty of
    //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    //GNU General Public License for more details.

    //You should have received a copy of the GNU General Public License
    //along with this program.  If not, see <http://www.gnu.org/licenses/>.

	//------------------------------------------------------------------------

	//FILE NAME: RealtimeDataTypes.h
	//class RealtimeQueueItem
	//class RealtimeQueue
	//-----------
	//Definition & Implementation of a thread safe queue(RealtimeQueue)
	//RealtimeQueueItem is an empty class used to set up a standart in using the queue.
	//P.S. You can use templates if you want.

#pragma once
#include <boost\thread\mutex.hpp>
#include <boost\thread\condition_variable.hpp>
#include <queue>
#include <list>
namespace re
{
	namespace core
	{
		//------------------------------------------------------------------------------------------------
		//RealtimeQueue
		//------------------------------------------------------------------------------------------------
		template<class T>
		class RealtimeQueue
		{
		public:
			RealtimeQueue() {}
			~RealtimeQueue() {}
			void push(T& data)
			{
				boost::mutex::scoped_lock lock(mutex_);
				queue_.push(data);
				lock.unlock();
				condition_var_.notify_one();
			}
			bool try_pop(T& data)
			{
				boost::mutex::scoped_lock lock(mutex_);
				if(queue_.empty())
				{
					return false;
				}
				data = queue_.front();
				queue_.pop();
				lock.unlock();
				return true;
			}
			void wait_pop(T& data)
			{
				boost::mutex::scoped_lock lock(mutex_);
				while(queue_.empty())
				{
					condition_var_.wait(lock);
				}
				data = queue_.front();
				queue_.pop();
			}
			bool is_empty()
			{
				boost::mutex::scoped_lock lock(m_mutex);
				return queue_.empty();
			}
		private:
			mutable boost::mutex mutex_;
			boost::condition_variable condition_var_;
			std::queue<T> queue_;
		};

		//------------------------------------------------------------------------------------------------
		//RealtimeList
		//------------------------------------------------------------------------------------------------

		template<class T>
		class RealtimeList
		{
		public:
			RealtimeList() {}
			~RealtimeList() {}
			void push_back(T& data)
			{
				boost::mutex::scoped_lock lock(mutex_);
				list_.push_back(data);
				lock.unlock();
			}
			void push_front(T& data)
			{
				boost::mutex::scoped_lock lock(mutex_);
				list_->push_front(data);
				lock.unlock();
			}
			void pop_back(T& data)
			{
				boost::mutex::scoped_lock lock(mutex_);
				data = list_.back();
				list_.pop_back();
			}
			void pop_front(T& data)
			{
				boost::mutex::scoped_lock lock(mutex_);
				data = list_.front();
				list_.pop_front();
			}
			void erase(T& data)
			{
				boost::mutex::scoped_lock lock(mutex_);
				std::list<T>::iterator i = list_.begin();
				while(i != list_.end())
				{
					if(*i == data)
					{
						break;
					}
					++i;
				}
				list_.erase(i);
			}
			void clear()
			{
				boost::mutex::scoped_lock lock(mutex_);
				list_.clear();
			}
			void insert(T& data, S32 pos)
			{
				boost::mutex::scoped_lock lock(mutex_);
				list_.insert(data, pos);
			}
			bool is_empty()
			{
				boost::mutex::scoped_lock lock(m_mutex);
				return list_.empty();
			}
		private:
			mutable boost::mutex mutex_;
			std::list<T> list_;
		};


	}
}